/**
 * Github Webhooks handler
 */

let EventEmitter = require('events').EventEmitter
let inherits = require('util').inherits
let crypto = require('crypto')
let bl = require('bl')
let bufferEq = require('buffer-equal-constant-time')

function signBlob(key, blob) {
    return 'sha1=' + crypto.createHmac('sha1', key).update(blob).digest('hex')
}

function isObject(obj) {
    return Object.prototype.toString.apply(obj) === '[object Object]'
}

function findHandler(url, arr) {
    let ret = arr[0]
    for (let i = 0; i < arr.length; i++) {
        if (url.split('?').shift() === arr[i].path) ret = arr[i]
    }
    return ret
}

function create(options) {
    // make it an EventEmitter, sort of
    handler.__proto__ = EventEmitter.prototype
    EventEmitter.call(handler)

    return handler

    function handler(req, res, callback) {
        function hasError(msg) {
            res.writeHead(400, { 'content-type': 'application/json' })
            res.end(JSON.stringify({ error: msg }))

            let err = new Error(msg)
            handler.emit('error', err, req)
            callback(err)
        }

        function checkType(options) {
            if (!isObject(options)) throw new TypeError('must provide an options object')

            if (typeof options.path !== 'string') throw new TypeError('must provide a \'path\' option')

            if (typeof options.secret !== 'string') throw new TypeError('must provide a \'secret\' option')
        }

        let currentOptions
        if (Array.isArray(options)) {
            currentOptions = findHandler(req.url, options)
        } else {
            currentOptions = options
        }

        checkType(currentOptions)

        if (req.url.split('?').shift() !== currentOptions.path) return callback()

        let sig = req.headers['x-gitee-token']
        let event = req.headers['x-gitee-event']
        let events = currentOptions.events

        if (!sig) return hasError('No x-gitee-token found on request')

        if (!event) return hasError('No x-gitee-event found on request')


        if (events && events.indexOf(event) === -1) {
            return hasError('x-gitee-event is not acceptable')
        }

        req.pipe(bl(function(err, data) {
            if (err)
                return hasError(err.message)

            var obj

            if (sig!==currentOptions.secret)
                return hasError('x-gitee-token does not match blob signature')

            try {
                obj = JSON.parse(data.toString())
            } catch (e) {
                return hasError(e)
            }

            res.writeHead(200, { 'content-type': 'application/json' })
            res.end('{"ok":true}')

            var emitData = {
                event: event,
                payload: obj,
                protocol: req.protocol,
                host: req.headers['host'],
                url: req.url,
                path: currentOptions.path
            }

            console.log(event)
            handler.emit(event, emitData)
            handler.emit('*', emitData)
        }))
    }
}

module.exports = create
